﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Download.Core;
using Download.Core.Extensions;
using Download.Core.UI;
using Download.Extension.Protocols;
using Download.Extension.Video;
using Download.Extension.SpeedLimit;
using Download.Extension.PersistedList;
using Download.Extension.AntiVirus;
using Download.Extension.Notifications;
using Download.Extension.AutoDownloads;
using Download.Extension.WindowsIntegration;
using Jermaine.UI;

namespace AutoUpdater
{
    public partial class DownloadControl : UserControl
    {
        #region 字段
        private DownloadManager downloadManger = DownloadManager.Instance;
        private Dictionary<ResourceLocation, string> fileMappers;
        private static readonly String GeneralDownloadInfo = Resource.GetString("DownloadControl.GeneralDownloadInfo");
        private static readonly String ItemDownloadInfo = Resource.GetString("DownloadControl.ItemDownloadInfo");
        private static readonly string TmpDir = Environment.GetEnvironmentVariable("TMP");
        #endregion

        #region 构造方法
        public DownloadControl(string[] urls)
            : this() {
            this.fileMappers = new Dictionary<ResourceLocation, string>();
            this.txtSpeed.Text = string.Empty;
            this.txtTotalProgress.Text = string.Empty;
            this.totalProgressBar.Value = 0;
            this.downloadProgressBar.Value = 0;
            FillFileMappers(urls);
            RegisterExtensions();
        }

        public DownloadControl() {
            InitializeComponent();

        }
        #endregion

        #region 事件方法

        /// <summary>
        /// 开始下载
        /// </summary>
        public void StartDownload() {
            DownloadControlStart();
        }

        /// <summary>
        /// 添加下载任务并启动
        /// </summary>
        private void DownloadControlStart() {

            foreach (var item in this.fileMappers) {
                downloadManger.Add(item.Key, null, item.Value, 1000, true);
            }

            var progressWather = new ProgressWatcher(downloadManger);
            progressWather.Updating += ProgressWatherUpdating;
            progressWather.Completed += ProgressWatherCompleted;
            progressWather.Initialized += ProgressWatherInitialized;
            progressWather.Start();

        }

        /// <summary>
        /// 初始化进度观察
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProgressWatherInitialized(object sender, EventArgs e) {
            var wathcer = sender as ProgressWatcher;
            var taskDoneCount = wathcer.TaskDoneCount;
            var totalCount = this.downloadManger.Downloads.Count;
            this.txtTotalProgress.Text = string.Format(GeneralDownloadInfo, taskDoneCount,
                   totalCount, 0, 0);

            this.txtSpeed.Text = string.Format(ItemDownloadInfo, string.Empty, 0, 0);

            OnStartDownloading();
        }

        /// <summary>
        /// 进度观察完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProgressWatherCompleted(object sender, EventArgs e) {
            UIInvoker.AsyncCall(this, () => {
                this.totalProgressBar.Value = 100;
                this.downloadProgressBar.Value = 100;
            });

            downloadManger.ClearEnded();
            OnDownloadCompleted();
        }

        /// <summary>
        /// 更新进度
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProgressWatherUpdating(object sender, ProgressWatcherEventArgs e) {
            var wathcer = sender as ProgressWatcher;
            var taskDoneCount = wathcer.TaskDoneCount;
            var totalCount = this.downloadManger.Downloads.Count;
            UIInvoker.AsyncCall(this, () => {
                this.txtTotalProgress.Text = string.Format(GeneralDownloadInfo, taskDoneCount,
                    totalCount, e.TotalProgress, e.TotalRate);
                this.totalProgressBar.Value = e.TotalProgress;
                this.txtSpeed.Text = string.Format(ItemDownloadInfo, e.FileName, e.Progress, e.Rate);
                this.downloadProgressBar.Value = e.Progress;
            });

            OnProgressUpdating(new ProgressUpdatingEventArgs {
                Percent = e.TotalProgress,
                Rate = e.TotalRate
            });
        }


        #endregion

        #region 方法
        protected void OnDownloadCompleted() {
            if (this.DownloadCompleted != null) {
                DownloadCompleted(this, EventArgs.Empty);
            }
        }

        private void OnProgressUpdating(ProgressUpdatingEventArgs e) {
            if (this.ProgressUpdating != null) {
                this.ProgressUpdating(this, e);
            }
        }

        private void OnStartDownloading() {
            if (this.StartDownloading != null) {
                this.StartDownloading(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 注册扩展
        /// </summary>
        private void RegisterExtensions() {
            Extensions = new List<IExtension>();
            Extensions.Add(new HttpFtpProtocolExtension());
        }

        /// <summary>
        /// 文件对
        /// </summary>
        /// <param name="urls"></param>
        private void FillFileMappers(string[] urls) {
            var path = System.IO.Path.Combine(TmpDir, "AutoUpdater");
            if (System.IO.Directory.Exists(path)) {
                System.IO.Directory.Delete(path, true);

            }
            System.IO.Directory.CreateDirectory(path);

            foreach (var item in urls) {
                var localFile = GetLocalFileName(new Uri(item));
                var resource = ResourceLocation.FromURL(item);
                fileMappers.Add(resource, localFile);
            }
        }

        /// <summary>
        /// 获取本地文件
        /// </summary>
        /// <param name="remoteUri"></param>
        /// <returns></returns>
        private string GetLocalFileName(Uri remoteUri) {
            string filename = remoteUri.Segments[remoteUri.Segments.Length - 1];

            filename = Uri.UnescapeDataString(filename);
            var path = System.IO.Path.Combine(TmpDir, "AutoUpdater");
            return System.IO.Path.Combine(path, filename);
        }

        #endregion

        #region 事件
        public event EventHandler DownloadCompleted;
        public event EventHandler<ProgressUpdatingEventArgs> ProgressUpdating;
        public event EventHandler StartDownloading;
        #endregion

        #region 属性
        public List<IExtension> Extensions { get; set; }
        #endregion

        public class ProgressUpdatingEventArgs : System.EventArgs
        {
            public int Percent { get; set; }
            public string Rate { get; set; }
        }
    }


}
